package com.yixing.tech.wms.statistics.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yixing.tech.wms.statistics.domain.entity.StkInventory;
import com.yixing.tech.wms.stock.out.StockOutService;
import com.yixing.tech.wms.stock.out.domain.Inventory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.bson.Document;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

@Service
@Slf4j
public class InventoryDataServiceImpl implements IInventoryDataService {

    @Resource
    StockOutService stockOutService;

    @Resource
    RedisTemplate<String, Object> redisTemplate;

    private final ObjectMapper objectMapper;

    public InventoryDataServiceImpl() {
        objectMapper = new ObjectMapper();
    }

    @Override
    public void insertInventoryIntoMesTable(Inventory inventory) {
        StkInventory stkInventory = new StkInventory();
        stkInventory.setInventoryId(inventory.getId());
        stkInventory.setWarehouseCode(inventory.getWarehouseCode());
        stkInventory.setLocationCode(inventory.getLocationCode());
        stkInventory.setContainerCode(inventory.getContainerCode());
        stkInventory.setMaterialCode(inventory.getMaterialCode());
        stkInventory.setColorName(inventory.getColorName());
        stkInventory.setLanguageName(inventory.getLanguageName());
        stkInventory.setBatchNo(inventory.getBatchNo());
        stkInventory.setRealNum(BigDecimal.valueOf(inventory.getRealNum()));
        stkInventory.setPartitionSide(inventory.getPartitionSide());

//        try {
//            int res = insertInventoryIntoMesTable(stkInventory);
//            log.info("保存mes库存信息:stkInventory[{}],res[{}]", stkInventory, res);
//        }catch (DuplicateKeyException ex) {
//            log.error("mes库存信息已存在:{}", stkInventory);
//        } catch (Exception ex) {
//            log.error("保存mes库存信息抛出异常:{}", ex);
//        }
    }

    @Override
    public void updateInventoryMesTable(Inventory inventory) {
        StkInventory stkInventory = new StkInventory();
        stkInventory.setWarehouseCode(inventory.getWarehouseCode());
        stkInventory.setLocationCode(inventory.getLocationCode());
        stkInventory.setContainerCode(inventory.getContainerCode());
        stkInventory.setMaterialCode(inventory.getMaterialCode());
        stkInventory.setColorName(inventory.getColorName());
        stkInventory.setLanguageName(inventory.getLanguageName());
        stkInventory.setBatchNo(inventory.getBatchNo());
        stkInventory.setRealNum(BigDecimal.valueOf(inventory.getRealNum()));
        stkInventory.setPartitionSide(inventory.getPartitionSide());
        stkInventory.setUpdateTime(new Date());

//        UpdateWrapper<StkInventory> updateWrapper = new UpdateWrapper<>();
//        updateWrapper.eq("inventory_id", inventory.getId());
//        try {
//            int mc = stkInventoryMapper.update(stkInventory, updateWrapper);
//            log.info("更新mes库存信息:inventoryId[{}], stkInventory[{}], mc[{}]", inventory.getId(), stkInventory, mc);
//        }catch (Exception ex) {
//            log.error("更新mes库存信息抛出异常:{}", ex);
//        }
    }

    @Override
    public void syncInventoryIntoMesTable() {
        List<Document> list = stockOutService.queryInventoryIdsRealNumGtZero();
        for(Document doc: list) {
            Inventory inventory = stockOutService.queryInventoryById(doc.getString("id"));
            if(ObjectUtils.isNotEmpty(inventory)) {
                insertInventoryIntoMesTable(inventory);
            }
        }
    }

    public boolean atomicStoreIfNotExists(String checkKey, String hashKey, String field, Object entity) {
        try {
            // 1. 准备Lua脚本
            String luaScript =
                    "local checkKey = KEYS[1]\n" +
                            "local hashKey = KEYS[2]\n" +
                            "local field = KEYS[3]\n" +
                            "local value = ARGV[1]\n" +

                            "-- 检查目标键是否存在\n" +
                            "if redis.call('EXISTS', checkKey) == 0 then\n" +
                            "    -- 存储到哈希表\n" +
                            "    redis.call('HSET', hashKey, field, value)\n" +
                            "    -- 设置检查键（防止后续请求重复存储）\n" +
                            "    redis.call('SET', checkKey, 'locked')\n" +
                            "    return 1\n" +
                            "else\n" +
                            "    return 0\n" +
                            "end";

            // 2. 序列化实体对象
            String jsonValue = objectMapper.writeValueAsString(entity);

            // 3. 创建Redis脚本对象
            DefaultRedisScript<Long> script = new DefaultRedisScript<>();
            script.setScriptText(luaScript);
            script.setResultType(Long.class);

            // 4. 执行脚本（原子操作）
            Long result = redisTemplate.execute(
                    script,
                    Arrays.asList(checkKey, hashKey, field),
                    jsonValue
            );

            return result != null && result == 1;
        } catch (Exception e) {
            throw new RuntimeException("Atomic storage failed", e);
        }
    }

//    @Override
//    public List<StkInventory> selectInventoryFromMesTable(StkInventory stkInventory, long limit) {
//        QueryWrapper<StkInventory> queryWrapper = new QueryWrapper<>();
//        if(ObjectUtils.isEmpty(stkInventory))
//            return stkInventoryMapper.selectList(queryWrapper);
//
//        if(ObjectUtils.isNotEmpty(stkInventory.getInventoryId())) {
//            queryWrapper.eq("inventory_id", stkInventory.getInventoryId());
//        }
//        if(ObjectUtils.isNotEmpty(stkInventory.getLocationCode())) {
//            queryWrapper.eq("location_code", stkInventory.getLocationCode());
//        }
//        if(ObjectUtils.isNotEmpty(stkInventory.getContainerCode())) {
//            queryWrapper.eq("container_code", stkInventory.getContainerCode());
//        }
//        if(ObjectUtils.isNotEmpty(stkInventory.getMaterialCode())) {
//            queryWrapper.eq("material_code", stkInventory.getMaterialCode());
//        }
//
//        Page<StkInventory> page = new Page<>(1, limit);
//        page.addOrder(OrderItem.asc("create_time"));
//        return stkInventoryMapper.selectList(page, queryWrapper);
//    }

//    private int insertInventoryIntoMesTable(StkInventory stkInventory) {
//        stkInventory.setCreateTime(new Date());
//        return stkInventoryMapper.insert(stkInventory);
//    }
}
